package at.ac.tuwien.isis.infret.ue3;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Vector;

import at.ac.tuwien.isis.infret.helper.DocumentContainer;
import at.ac.tuwien.isis.infret.ue3.interfaces.IHtmlOutput;

public class HtmlOutput implements IHtmlOutput {
	private PrintWriter pw;
	private String directoryPath;
	private DecimalFormat df = new DecimalFormat("#.####");
	private String filePath;
	
	public HtmlOutput(String filePath) throws IOException{
		this.filePath =  filePath;
		
		 directoryPath = filePath.replace(".html", ""+File.separatorChar);
		 //System.out.println(directoryPath);
		 File path = new File(directoryPath);
		 if (!path.exists()){
			 path.mkdir();
		 }
	}
	@Override
	public void writeToHtml(
			HashMap<DocumentContainer, Double> finalResult,Vector<TreeMap<DocumentContainer,Double>> resultLists,
			Vector<String> queryList, String distanceFunction, Vector<String> featureFiles, int kBest) {
		try {
			pw = new PrintWriter(new FileWriter(filePath));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		pw.println("<html><body>");
		pw.println("Output File for Query: <br>");
		//System.out.println(queryList);
		for(String query : queryList)
			pw.print(query+" ");
		
		
		pw.println("<br><br>Using Distance Function: <br>");
		pw.println(distanceFunction);
		
		
		/*	
		pw.println("<br><br>Using Index File(s): <br>");
		for( String feature : featureFiles)
			pw.println(feature+"<br>");
		*/
		//min max average across all indices
		Double [] stat = {Double.MAX_VALUE,0.0,0.0};
		
		pw.println("<br>kBest List (by minimum distance) for each index<table Border>");
		pw.println("<tr>");
		for(int i = 0; i < resultLists.size();i++){
			pw.println("<td>");
			Double actStat [] = 
				this.writeHTMLresultList(resultLists, i, featureFiles.get(i), kBest);
			pw.println("<a href=\""+this.directoryPath.replaceAll("output"+File.separatorChar, "")+featureFiles.get(i) +".html\">"+featureFiles.get(i)+"</a>");
			//this.writeHTMLresultList(resultLists, i, featureFiles.get(i), kBest);
			pw.println("</td>");
			
			if (actStat[0] < stat[0])
				stat[0] = actStat[0];

			if (actStat[1] > stat[1])
				stat[1] = actStat[1];
			
			stat[2] += actStat[2];
		}
		stat[2]= stat[2]/((double) resultLists.size());
		pw.println("</tr>");
		pw.println("</table>");
		

		
		pw.println("<br>kBest statistics across all indices' resultlists<table Border>");
		
		pw.println("<tr>");
		pw.println("<td>Minimum Distance</td>" +
				"<td>Maximum Distance</td>" +
				"<td>Average Distance</td>");
		pw.println("</tr>");
		pw.println("<tr>");
		pw.println("<td>"+df.format(stat[0])+"</td>" +
				"<td>"+df.format(stat[1])+"</td>" +
				"<td>"+df.format(stat[2])+"</td>");
		
		pw.println("</tr>");
		pw.println("</table>");
		
		
		pw.println("<br>Merged Output List: Documents of minimal average rank across all Indices (modified output of UE2)<table Border>");
		
		
		
	//	for(TreeMap<Double, DocumentContainer> map : resultLists){

		pw.println("<tr>");
		pw.println("<td>Document Name</td>" +
				"<td>Minimum Distance</td>" +
				"<td>Sum of occurences <br>in kBest of each Index</td>" +
				"<td>Average Rank</td>" +
				"<td>Average Distance</td>");
		pw.println("</tr>");
		Iterator<Double> minIterator = finalResult.values().iterator();
		for(DocumentContainer doc : finalResult.keySet()){
			pw.println("<tr>");
			pw.println("<td>"+doc.getClassname()+"/"+doc.getDocumentname()+"</td>" +
					"<td>"+df.format(minIterator.next())+"</td>"+
					"<td>"+Statistics.SumofOcc(doc, resultLists,kBest)+"</td>" +
					"<td>"+df.format(Statistics.avgRank(doc, resultLists))+"</td>" +
					"<td>"+df.format(Statistics.avgDistance(doc, resultLists))+"</td>");
			pw.println("</tr>");
		}
		pw.println("</table>");
	//	}
		
		
		pw.println("</body></html>");
		pw.flush();
		pw.close();
	}
	public Double[] writeHTMLresultList(Vector<TreeMap<DocumentContainer,Double>> resultLists, 
			int index, String featureName, int kBest){
		PrintWriter sub = null;
		//Double ret[];
		try {

			sub = new PrintWriter(new FileWriter(this.directoryPath+featureName+".html"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//System.out.println(this.directoryPath+featureName+".html");
		Vector<TreeMap<DocumentContainer,Double>> temp = new Vector<TreeMap<DocumentContainer,Double>>();
		temp.add(resultLists.get(index));
		HashMap<DocumentContainer,Double> finalResult = Statistics.getkBest(temp, kBest);
		sub.println("<body><html>");
		sub.println("Index File: "+featureName);
		sub.println("<table border>");
		sub.println("<tr>");
		sub.println("<td>Document Name</td>" +
				"<td>Minimum Distance</td>" +
				"<td>Sum of occurences <br>in kBest of all Indices</td>" +
				"<td>Average Rank across all Indices</td>" +
				"<td>Average Distance across all Indices</td>");
		sub.println("</tr>");
		Iterator<Double> minIterator = finalResult.values().iterator();
		for(DocumentContainer doc : finalResult.keySet()){
			sub.println("<tr>");
			sub.println("<td>"+doc.getClassname()+"/"+doc.getDocumentname()+"</td>" +
					"<td>"+df.format(minIterator.next())+"</td>"+
					"<td>"+Statistics.SumofOcc(doc, resultLists,kBest)+"</td>" +
					"<td>"+df.format(Statistics.avgRank(doc, resultLists))+"</td>" +
					"<td>"+df.format(Statistics.avgDistance(doc, resultLists))+"</td>");
			sub.println("</tr>");
		}
		sub.println("</table>");
		sub.println("</body></html>");
		sub.flush();
		sub.close();
		
		return Statistics.getkBestStatistics(finalResult);
	}
	public void writeGlobalToHtml(String path,Vector<String> indexNames, Vector<String> docNames, Vector<Double[][]> distanceMatrices, int kBest){
		
		PrintWriter glob = null;
		GlobalQueryHandler global = new GlobalQueryHandler(distanceMatrices);
		Vector<Double[][]> rankMatrices = global.getRankMatrices();
		Double[][] mergedRankMatrix = global.getMergedRankMatrix(rankMatrices);
		
		
		//Double ret[];
		try {

			glob = new PrintWriter(new FileWriter(path));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		glob.println("<html><body>");
		glob.println("Global query statistics<br><br> All result Lists are size kBest = "+kBest+"<br>");
		glob.println("<table border>");
		
		
		glob.println("<td>Document Name</td>");
		for(String index : indexNames){
			glob.println("<td>minimal d in set "+index+"</td>");
			glob.println("<td>maximal d in set "+index+"</td>");
			glob.println("<td>average d in set "+index+"</td>");
		}
		glob.println("<td>overall # of documents able to query</td>");
		for(String index : indexNames){
			glob.println("<td># of documents able to query, in set "+index+"</td>");
		}
		glob.println("<td># of documents able to query, in merged set</td>");
		glob.println("</tr>");
		
		//currDoc is document that needs to be queried
		for(int currDoc = 0; currDoc < docNames.size();currDoc++){
			if(currDoc%10 == 0)System.out.print(".");
			glob.println("<tr>");
			glob.println("<td>"+docNames.get(currDoc)+"</td>");
			
			// MIN MAX AVG for each index
			for(int i = 0; i < indexNames.size();i++){
				Double [] stats = Statistics.getIndexStatistics(distanceMatrices.get(i), currDoc);		
				glob.println("<td>"+df.format(stats[0])+"</td>"+"<td>"+df.format(stats[1])+"</td>"+"<td>"+df.format(stats[2])+"</td>");
			}
			//Number of documents that can query currDoc
			int queryable = 0;
			
			//0-indexNames.size() queryable documents in each list, last one = merged list
			int queryIn[] = new int[indexNames.size()+1];
			
			for(int i = 0; i < docNames.size(); i++){
				boolean queryFound = false; 
				
				if(i == currDoc)continue;
				if(mergedRankMatrix[i][currDoc]<kBest){
					queryFound = true;
					queryIn[queryIn.length-1]++;
				}
				for( int set = 0 ; set < indexNames.size(); set++ ){
					if(rankMatrices.get(set)[i][currDoc]<kBest){
						queryFound = true;
						queryIn[set]++;
					}
				}
				if(queryFound)queryable++;
			}
			glob.println("<td>"+df.format(queryable)+"</td>");
			
			//Number of documents that can query in each index
			for(int i = 0; i < queryIn.length; i++){
				glob.println("<td>"+df.format(queryIn[i])+"</td>");
			}
			
			glob.println("</tr>");
		}
		
		glob.println("</table>");
		glob.println("</body></html>");
		glob.flush();
		glob.close();
		
		
		
	}
}
